/*
    This file is part of Slydini.

    Slydini is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Slydini is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Slydini.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "processor.h"
#include "processor.moc"
#include "gui/right_menu.h"
double scale = 1.3;
Configuration *c = Configuration::getConfiguration("configuration.xml");

Processor::Processor(QWidget *parent) : QWidget(parent) {
	this->painterImage = new QImage(c->queryInt("desktop/width"),c->queryInt("desktop/height"),QImage::Format_RGB32);
	this->swidget = NULL;
	this->frame_count = 0;
	this->image = NULL;
	this->image_prev = NULL;
	this->background_image = NULL;
	this->imageBW = NULL;
	this->smallImage = NULL;
	this->capture = NULL;
	this->currentlyClicked = false;
}

int Processor::initialize(int argc, char **argv) {
	printf("Initializing capturing... ");
	if(argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
		capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - '0' : 0 );
	if (!capture)
		capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - '0' : 0 );
	else if( argc == 2 )
		capture = cvCaptureFromAVI( argv[1] );
	if (!capture) {
		printf("FAILED\n");
		return 1;
	} else {
		printf("OK\n");
	}

	cvSetCaptureProperty(capture,CV_CAP_PROP_FRAME_WIDTH,320);
	cvSetCaptureProperty(capture,CV_CAP_PROP_FRAME_HEIGHT,240);

	t = (double)cvGetTickCount();

	// fingers_history = new FingersHistory();

	cvNamedWindow( "BW", 1 );


	gestureDetector = GestureDetector::getInstance();

	Configuration *c = Configuration::getConfiguration("configuration.xml");
	handTracker = new HandTracker(c->queryInt("hands/clickThreshold"));

	this->swidget = new SWidget(c->queryInt("desktop/width"),c->queryInt("desktop/height"), this);
	this->swidget->setGeometry(0,0,c->queryInt("desktop/width"),c->queryInt("desktop/height"));
	this->swidget->setWindowFlags(Qt::FramelessWindowHint);

	mouse = new Mouse(c->queryInt("display"));
	mouse->reset();
	
	resized_image = cvCreateImage( cvSize(c->queryInt("desktop/width"),c->queryInt("desktop/height")), 8, 3 );

	return 0;
}

void Processor::captureFrame() {
	IplImage* frame = 0;

	


	frame = cvQueryFrame(capture);

	if (!frame)
		return;

	if (image)		 
		cvCopy(image, image_prev, 0);

	if (!image) {
		image = cvCreateImage(cvSize(frame->width, frame->height), IPL_DEPTH_8U, frame->nChannels);
		image_prev = cvCreateImage(cvSize(frame->width, frame->height), IPL_DEPTH_8U, frame->nChannels);
		imageBW = cvCreateImage(cvSize(frame->width, frame->height), IPL_DEPTH_8U, 1);
		
		smallImage = cvCreateImage( cvSize( cvRound (image->width/scale), cvRound (image->height/scale)), 8, 1 );
	}

    if(frame->origin == IPL_ORIGIN_TL)	{
		cvCopy(frame, image, 0);
	} else
		cvFlip(frame, image, 0);

	

	cvCvtColor( image, imageBW, CV_BGR2GRAY );
	cvResize(imageBW, smallImage, CV_INTER_LINEAR);
}

void Processor::releaseFrame() {
	cvReleaseImage(&image);
	cvReleaseImage(&image_prev);
	cvReleaseImage(&imageBW);
	cvReleaseImage(&smallImage);

}

void Processor::processFrame() {
	captureFrame();
	// Frame analysis goes here

	FrameEvaluation *frameEvaluation = FrameEvaluation::getInstance();

	frameEvaluation->update(image);


	handTracker->update(frameEvaluation->getHand());

	if (handTracker->handDetected()) {
		printf("hand tracker detected a hand\n");
		TrackedHand trackedHand = handTracker->getTrackedHand();
		// wykrywanie myszy
		mouse->moveMouse(trackedHand.position.x, trackedHand.position.y);

		if (trackedHand.state.clicked && !currentlyClicked) {

			mouse->mouseDown();
			currentlyClicked = true;
		}
		if (!trackedHand.state.clicked && currentlyClicked) {
			mouse->mouseUp();
			currentlyClicked = false;
		}
	} else if (currentlyClicked){
		mouse->mouseUp();
		currentlyClicked=false;  
	}

	//
	//	gestureDetector->setCurrentPosition(position);
	//	Gesture *gesture = gestureDetector->getCurrentGesture();
	//	if (gesture) {
	//	...
	//	}

	// Frame analysis finished
	this->update();
	//releaseFrame();
	frame_count++;

	//		printf("%d: frame time: %.0fms\n",frame_count,((double)cvGetTickCount()-t)/1000);
	t = (double)cvGetTickCount();
}

	void Processor::keyReleaseEvent(QKeyEvent *event) {
		if (event->key() == Qt::Key_Escape)
			emit quit();
	}



void Processor::paintEvent(QPaintEvent* event) {
	QPainter p(this);
	QPainter imagePainter(this->painterImage);
	//SWidget::color = Qt::blue;
	//SWidget::penStyle = SWidget::symetric;


if (background_image != NULL)
               delete background_image;
	if (image) {
		uchar *data = NULL;
        QImage *new_background_image = swidget->rmenu->ChoosenPicture();
	    if (new_background_image == NULL) {
            cvResize(image, resized_image, CV_INTER_LINEAR );
            
		    background_image = IplImageToQImage(resized_image, data);
         }
         else {
              background_image = new QImage(new_background_image->scaled(background_image->width(),background_image->height()));
	     }


if(background_image == NULL)
		fflush(0);

		imagePainter.drawImage(0,0,*background_image);

		fflush(0);
		if (data!=NULL)
			delete data;
	}
	p.drawImage(0,0,*this->painterImage);

}
